package cn.mujiankeji.mbrowser.工具.操作

import android.util.Patterns
import 操作.工具类.left
import 操作.工具类.left2
import 操作.工具类.right2
import 操作.工具类.文本操作.取地址主机
import 操作.工具类.文本操作.取地址前缀
import java.util.regex.Pattern

/**
 * 地址操作工具类
 * 
 * 提供URL和文件路径相关的处理功能
 */
object 地址操作 {

    // 图片文件扩展名列表
    private val 图片扩展名列表 = listOf(
        "jpg", "jpeg", "png", "gif", "bmp", "webp", "svg", "ico", "tiff", "heic", "heif"
    )

    // 视频文件扩展名列表
    private val 视频扩展名列表 = listOf(
        "mp4", "avi", "mkv", "mov", "wmv", "flv", "f4v", "webm", "mpeg", "mpg", "m4v", 
        "3gp", "ts", "m3u8", "rm", "rmvb"
    )

    // 音频文件扩展名列表
    private val 音频扩展名列表 = listOf(
        "mp3", "wav", "ogg", "m4a", "aac", "flac", "ape", "wma", "mid", "midi"
    )

    /**
     * 判断地址是否为图片
     * 
     * @param 地址 要检查的URL或文件路径
     * @return 如果是图片则返回true，否则返回false
     */
    fun 是否为图片(地址: String): Boolean {
        val 后缀 = 取后缀(地址).lowercase()
        return 后缀 in 图片扩展名列表
    }

    /**
     * 判断地址是否为视频
     * 
     * @param 地址 要检查的URL或文件路径
     * @return 如果是视频则返回true，否则返回false
     */
    fun 是否为视频(地址: String): Boolean {
        val 后缀 = 取后缀(地址).lowercase()
        return 是否为视频格式(后缀)
    }

    /**
     * 判断地址是否为音频
     * 
     * @param 地址 要检查的URL或文件路径
     * @return 如果是音频则返回true，否则返回false
     */
    fun 是否为音频(地址: String): Boolean {
        val 后缀 = 取后缀(地址).lowercase()
        return 后缀 in 音频扩展名列表
    }

    fun 是否为视频地址(地址 : String) :Boolean{
        return 取后缀(地址).let {
            是否为视频格式(it)
        }
    }
    /**
     * 判断后缀是否属于视频文件格式，如 mp4 ts
     * 
     * @param 后缀 文件扩展名，不包含点号
     * @return 如果是视频扩展名则返回true，否则返回false
     */
    fun 是否为视频格式(后缀: String): Boolean {
        return 后缀.lowercase() in 视频扩展名列表
    }

    fun 是否为图片格式(后缀 : String) : Boolean{
        return 后缀.lowercase() in 图片扩展名列表
    }
    /**
     * 返回地址的后缀，如 xxx.jpg 返回 jpg，不含小数点
     * 无后缀返回空字符串
     * 
     * @param 地址 要分析的URL或文件路径
     * @return 文件扩展名，不包含点号
     */
    fun 取后缀(地址: String): String {
        // 处理URL参数和锚点
        val 基础地址 = 地址.substringBefore('?').substringBefore('#')
        
        // 获取最后一个点后面的内容
        val 最后一点位置 = 基础地址.lastIndexOf('.')
        if (最后一点位置 == -1 || 最后一点位置 == 基础地址.lastIndexOf('/')) {
            return ""
        }
        
        return 基础地址.substring(最后一点位置 + 1)
    }

    /**
     * 返回地址的前缀，如 https://xxx.xx 返回 https
     * 无前缀返回空字符串
     * 
     * @param 地址 要分析的URL
     * @return 协议前缀，如http, https等
     */
    fun 取前缀(地址: String): String {
        val 前缀 = 取地址前缀(地址)
        if (前缀.isNotEmpty()) {
            return 前缀
        }
        
        val 冒号位置 = 地址.indexOf(':')
        if (冒号位置 > 0) {
            return 地址.substring(0, 冒号位置)
        }
        
        return ""
    }

    /**
     * 从地址或路径中读取文件名
     * 
     * @param 地址 要分析的URL或文件路径
     * @param 含后缀 是否包含文件扩展名
     * @return 文件名，如果含后缀为true则包含扩展名
     */
    fun 取文件名(地址: String, 含后缀: Boolean): String {
        // 处理URL参数和锚点
        val 基础地址 = 地址.substringBefore('?').substringBefore('#')
        
        // 获取最后一个斜杠后面的内容
        val 最后一斜杠位置 = 基础地址.lastIndexOf('/')
        if (最后一斜杠位置 == -1) {
            return if (含后缀) 基础地址 else 基础地址.substringBeforeLast('.')
        }
        
        val 文件名 = 基础地址.substring(最后一斜杠位置 + 1)
        return if (含后缀) 文件名 else 文件名.substringBeforeLast('.')
    }

    /**
     * 从地址中获取主机地址，如 http://a.nr.cn/xxx 返回 a.nr.cn
     * 
     * @param url 要分析的URL
     * @return 域名，包含子域名
     */
    fun 取地址域名(url: String): String {
        // 先取地址  http://a.nr.cn/xxx -> a.nr.cn
        var host = 取地址主机(url)

        // 只要后两个值    [a].[nr].[cn]
        host.split(".").let {
            if (it.size > 2){
                host = "${it[it.size - 2]}.${it[it.size - 1]}"
            }
        }
        return host
    }

    /**
     * 从地址中获取完整的主机名（包含子域名）
     * 
     * @param url 要分析的URL
     * @return 完整主机名，如www.example.com
     */
    fun 取完整主机名(url: String): String {
        return 取地址主机(url)
    }

    /**
     * 获取地址、路径的绝对路径
     * 检测URL 是否带 域名  没有则从  判断URL中获取
     * @param url1 需要检测的相对或绝对url
     * @param url2  进行比对的url ，此URL应当含有绝对路径
     * @return 转换后的绝对URL
     */
    fun 取绝对地址(url1: String, _url2: String?=null): String {
        // 原生
        if (url1.startsWith("m:") || url1.startsWith("#")) return url1

        // 没有匹配值
        if (url1.isEmpty()) return url1

        // 添加协议头
        if (_url2.isNullOrEmpty()){
            if (url1.startsWith("//")) {
                return "http:$url1"
            }
            url1.left("://").let {
                if (it == null || it.contains(".")) return "http://$url1"
            }
        }

        // 拥有完整的地址也不用管
        url1.left("://")?.let {
            if (it.contains(Regex("[\\u4e00-\\u9fa5A-Za-z_]+[\\u4e00-\\u9fa5A-Za-z0-9_]"))) return url1
        }

        var url2 = _url2!!

        // hosturl 必须带前缀
        if (取地址前缀(url2).isEmpty()) {
            url2 = "http://$url2"
        }

        // 双斜杠：缺少http头   ...   //xx.com -> http://xxx.com
        if (url1.startsWith("//")) {
            return 取绝对地址2(url2.left("//") + url1) // 从判断URL中引入 HTTP  毕竟有可能为 https 有些网站不支持跳转
        }

        // 单斜杆：缺少服务器地址 ...  /index.html -> http://xx.com/index.html
        else if (url1.startsWith("/")) {
            val left = url2.left(9,"/") ?: url2
            return 取绝对地址2(left + url1)
        }

        // ./ 从当前目录开始
        else if (url1.startsWith("./")){
            val dir = url2.left2("/") ?: return url1
            if (!dir.contains(".")) return url1 // 可能返回的是协议头中的斜杠  那就是条件不达成
            return 取绝对地址2(dir + "/" + url1.substring(2))
        }

        // ../ 从上级目录开始
        else if (url1.startsWith("../")){
            var dir = url2.left2("/") ?: return url1
            dir = dir.right2("/") ?: return url1
            if (!dir.contains(".")) return url1 // 可能返回的是协议头中的斜杠  那就是条件不达成
            return 取绝对地址2(dir+"/" + url1.substring(3))
        }

        // 不带符号，从当前目录开始
        else{
            val dir = url2.left2("/") ?: return url1
            if (!dir.contains(".")) return url1 // 可能返回的是协议头中的斜杠  那就是条件不达成
            return 取绝对地址2("$dir/$url1")
        }
    }
    
    private fun 取绝对地址2(str: String): String = str.replace("\\/","/")

    /**
     * 提取URL中的路径部分，不包括域名和参数
     * 
     * @param url 要分析的URL
     * @return URL的路径部分
     */
    fun 取URL路径(url: String): String {
        var 路径 = ""
        
        try {
            // 去除协议和域名部分
            val 主机名结束位置 = url.indexOf("/", url.indexOf("://") + 3)
            if (主机名结束位置 != -1) {
                路径 = url.substring(主机名结束位置)
            }
            
            // 去除查询参数和锚点
            val 参数开始位置 = 路径.indexOf('?')
            if (参数开始位置 != -1) {
                路径 = 路径.substring(0, 参数开始位置)
            }
            
            val 锚点开始位置 = 路径.indexOf('#')
            if (锚点开始位置 != -1) {
                路径 = 路径.substring(0, 锚点开始位置)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        
        return 路径
    }

    /**
     * 从URL中提取查询参数
     * 
     * @param url 要分析的URL
     * @return 参数Map，键为参数名，值为参数值
     */
    fun 提取URL参数(url: String): Map<String, String> {
        val 参数Map = mutableMapOf<String, String>()
        
        try {
            val 问号位置 = url.indexOf('?')
            if (问号位置 == -1) return 参数Map
            
            val 参数部分 = url.substring(问号位置 + 1).split('&')
            for (参数 in 参数部分) {
                val 等号位置 = 参数.indexOf('=')
                if (等号位置 != -1) {
                    val 键 = 参数.substring(0, 等号位置)
                    val 值 = if (等号位置 < 参数.length - 1) 参数.substring(等号位置 + 1) else ""
                    参数Map[键] = 值
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        
        return 参数Map
    }

    /**
     * 将参数添加到URL
     * 
     * @param url 基础URL
     * @param 参数Map 要添加的参数，键值对
     * @return 添加参数后的URL
     */
    fun 添加URL参数(url: String, 参数Map: Map<String, String>): String {
        if (参数Map.isEmpty()) return url
        
        val 基础URL = url.split('#')[0]
        val 锚点 = if (url.contains('#')) '#' + url.split('#')[1] else ""
        
        val 分隔符 = if (基础URL.contains('?')) '&' else '?'
        val 参数字符串 = 参数Map.entries.joinToString("&") { "${it.key}=${it.value}" }
        
        return "$基础URL$分隔符$参数字符串$锚点"
    }

    /**
     * 判断URL是否为有效的网址
     * 
     * @param url 要检查的URL
     * @return 如果是有效URL则返回true，否则返回false
     */
    fun 是否有效URL(url: String): Boolean {
        val 正则 = Regex("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]")
        return 正则.matches(url)
    }

    /**
     * 标准化URL格式，处理常见问题
     * 
     * @param url 原始URL
     * @return 标准化后的URL
     */
    fun 标准化URL(url: String): String {
        var 标准URL = url.trim()
        
        // 添加缺失的协议
        if (!标准URL.startsWith("http://") && !标准URL.startsWith("file://") && !标准URL.startsWith("https://") && !标准URL.startsWith("ftp://")) {
            if (标准URL.startsWith("//")) {
                标准URL = "https:$标准URL"
            } else if (!标准URL.contains("://")) {
                标准URL = "https://$标准URL"
            }
        }
        
        // 移除多余的斜杠
        标准URL = 标准URL.replace("(?<!:)/{2,}".toRegex(), "/")
        
        return 标准URL
    }


    /**
     * 判断字符串是否为URL
     * 支持以下格式：
     * - 完整URL：http://example.com, https://example.com
     * - 域名：example.com, www.example.com
     * - IP地址：192.168.1.1
     */
    fun isUrl(text: String): Boolean {
        val trimmedText = text.trim()

        // 如果为空，不是URL
        if (trimmedText.isEmpty()) return false

        // 检查是否是完整的URL（以http://或https://开头）
        if (trimmedText.startsWith("http://") || trimmedText.startsWith("https://")) {
            return Patterns.WEB_URL.matcher(trimmedText).matches()
        }

        // 检查是否包含常见的域名后缀
        val commonTlds = listOf(".com", ".cn", ".net", ".org", ".edu", ".gov", ".io", ".app", ".me",".cc")
        if (commonTlds.any { trimmedText.contains(it) }) {
            // 尝试添加http://前缀后再检查
            return Patterns.WEB_URL.matcher("http://$trimmedText").matches()
        }

        // 检查是否是IP地址
        val ipPattern = Pattern.compile(
            "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"
        )
        if (ipPattern.matcher(trimmedText).matches()) {
            return true
        }

        // 检查是否包含至少一个点，且不以点开头或结尾（可能是域名）
        if (trimmedText.contains(".") && !trimmedText.startsWith(".") && !trimmedText.endsWith(".")) {
            val parts = trimmedText.split(".")
            // 域名至少有两部分，且每部分不为空
            if (parts.size >= 2 && parts.all { it.isNotEmpty() }) {
                return true
            }
        }

        return false
    }
}